BaseType_t xTaskCreate (
    TaskFunction_t pxTaskCode, // Address of the associated task handler
    const char* const pcName, // A descriptive name to identify this task
    const configSTACK_DEPTH_TYPE usStackDepth, // Amount of stack memory allocated to this task (memory in words not in bytes)
    void* const pvParameters, // Pointer of the data which needs to be passed to the task handler once it gets scheduled
    UBaseType_t uxPrioritym // Task priority value
    TaskHandle_t* const pxCreatedTask // Used to save the task handle (an address of the task created)
)
void vATaskFunction( void *pvParameters) {
    for ( ; ; ) {
        --Task application code here.
    }
}
目標: 建立Task1 & Task2,步驟如下:
 
/* Includes ------------------------------------------------------------------*/
#include "main.h" //原有的Code
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h> // 新增,因為Task1 & Task2是要print
#include "FreeRTOS.h" // 新增,因為要使用FreeRTOS的Kernel
#include "task.h" // 新增,從xTaskCreate() 發現,要引用task.h才能使用此function
/* USER CODE END Includes */
int main(void) 
{
  /* USER CODE BEGIN 1 */
  TaskHandle_t task1_handle; //增加,變數
  TaskHandle_t task2_handle; //增加,變數
  
  BaseType_t status; //增加,變數
  /* USER CODE END 1 */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  
  status = xTaskCreate(task1_handler, "Task-1", 200, "Hello World from Task-1", 4, &task1_handle); 
  configASSERT(status == pdPASS); //configASSERT 確保任務創建成功,檢查 status 是否等於 pdPASS,pdPASS 表示任務創建成功,如果不等於 pdPASS,則觸發 assert 失敗,導致系統停下來進行除錯
  
  xTaskCreate(task2_handler, "Task-2", 200, "Hello World from Task-2", 4, &task2_handle);
  configASSERT(status == pdPASS);
  
  //start the freeRTOS scheduler
  vTaskStartScheduler(); // if the control comes here means the scheduler has failed due to insufficient memory in heap.
  /* USER CODE END 2 */
  HAL_GPIO_Init(MEMS_INT2_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
static void task1_handler(void* parameters) //增加,函式
{
    while (1)
	{
		printf("%s\n", (char*)parameters);
	}
}
static void task2_handler(void* parameters) //增加,函式
{
	while (1)
	{
		printf("%s\n", (char*)parameters);
	}
}
/* USER CODE END 4 */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */ //PFP: Private Function Prototype
static void task1_handler(void* parameters); //增加,靜態函式宣告
static void task2_handler(void* parameters); //增加,靜態函式宣告
/* USER CODE END PFP */
#include <sys/time.h>
#include <sys/times.h>
//以下為新增的ITM Code
//Debug Exception and Monitor Control Register base address
#define DEMCR        			*((volatile uint32_t*) 0xE000EDFCU )
/* ITM register addresses */
#define ITM_STIMULUS_PORT0   	*((volatile uint32_t*) 0xE0000000 )
#define ITM_TRACE_EN          	*((volatile uint32_t*) 0xE0000E00 )
void ITM_SendChar(uint8_t ch)
{
	//Enable TRCENA
	DEMCR |= ( 1 << 24);
	//enable stimulus port 0
	ITM_TRACE_EN |= ( 1 << 0);
	// read FIFO status in bit [0]:
	while(!(ITM_STIMULUS_PORT0 & 1));
	//Write to ITM stimulus port0
	ITM_STIMULUS_PORT0 = ch;
}
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}
修改為:
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		//__io_putchar(*ptr++);
		ITM_SendChar(*ptr++);
	}
	return len;
}
#define configUSE_IDLE_HOOK				1
修改為:
#define configUSE_IDLE_HOOK				0
void task_handler(void* parameters)
{
	/*These Local variables will get created in Task's Private stack memory */
    /*More variables, more stack consumption */
    int var1, var2;
    
    /*This static variable will not get created in Task's private stack memoyr */
    /*在global area創建 */
    static int staticVar1;
    
    while(1) {
        /*Task's work here */
    }
    
    /*Before exit, clean up */
    vTaskDelete(NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//					Implementation of printf like feature using ARM Cortex M3/M4/ ITM functionality
//					This function will not work for ARM Cortex M0/M0+
//					If you are using Cortex M0, then you can use semihosting feature of openOCD
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//Debug Exception and Monitor Control Register base address
#define DEMCR        			*((volatile uint32_t*) 0xE000EDFCU )
/* ITM register addresses */
#define ITM_STIMULUS_PORT0   	*((volatile uint32_t*) 0xE0000000 )
#define ITM_TRACE_EN          	*((volatile uint32_t*) 0xE0000E00 )
void ITM_SendChar(uint8_t ch)
{
	//Enable TRCENA
	DEMCR |= ( 1 << 24);
	//enable stimulus port 0
	ITM_TRACE_EN |= ( 1 << 0);
	// read FIFO status in bit [0]:
	while(!(ITM_STIMULUS_PORT0 & 1));
	//Write to ITM stimulus port0
	ITM_STIMULUS_PORT0 = ch;
}
應該可以Build過了! 明天再說怎麼觀察preemption的現象~